package traces

import (
	"fmt"
	"log/slog"
	"runtime"
	"strconv"
	"strings"
	"time"
)

const (
	DefaultStackSize uint = 4096
)

func Stack(skip int) string {
	// 最多跟踪32层
	pcs := make([]uintptr, 32)
	n := runtime.Callers(skip, pcs)
	frames := runtime.CallersFrames(pcs[:n])

	var sb strings.Builder
	for {
		frame, more := frames.Next()
		pos := strings.LastIndex(frame.Function, "/")
		sb.WriteByte('\n')
		sb.WriteByte('\t')
		sb.WriteString(frame.File)
		sb.WriteByte(':')
		sb.WriteString(strconv.Itoa(frame.Line))
		sb.WriteByte(' ')
		sb.WriteString(frame.Function[pos+1:])

		if !more {
			break
		}
	}

	return sb.String()
}

func TrackTime(name string, start time.Time) time.Duration {
	elapsed := time.Since(start)
	slog.Info(fmt.Sprintf("%s elapsed: %d ms", name, elapsed.Milliseconds()))
	return elapsed
}

func GetCurrentStack() string {
	buf := make([]byte, DefaultStackSize)
	n := runtime.Stack(buf, false)
	return string(buf[:n])
}
